home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.Lib / PICTControl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-02  |  13.6 KB  |  591 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:         pictcontrol.c
  5. ** Written by:      Eric Soldan
  6. **
  7. ** Copyright © 1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19.  
  20.  
  21. /*****************************************************************************/
  22.  
  23.  
  24.  
  25. #ifndef __PICTCONTROL__
  26. #include "PICTControl.h"
  27. #endif
  28.  
  29. #ifndef __CONTROLS__
  30. #include <Controls.h>
  31. #endif
  32.  
  33. #ifndef __DTSLib__
  34. #include "DTS.Lib.h"
  35. #endif
  36.  
  37. #ifndef __ERRORS__
  38. #include <Errors.h>
  39. #endif
  40.  
  41. #ifndef __FONTS__
  42. #include <Fonts.h>
  43. #endif
  44.  
  45. #ifndef __GWLAYERS__
  46. #include "GWLayers.h"
  47. #endif
  48.  
  49. #ifndef __MEMORY__
  50. #include <Memory.h>
  51. #endif
  52.  
  53. #ifndef __PACKAGES__
  54. #include <Packages.h>
  55. #endif
  56.  
  57. #ifndef __RESOURCES__
  58. #include <Resources.h>
  59. #endif
  60.  
  61. #ifndef __STRINGUTILS__
  62. #include "StringUtils.h"
  63. #endif
  64.  
  65. #ifndef __UTILITIES__
  66. #include "Utilities.h"
  67. #endif
  68.  
  69.  
  70.  
  71. /*****************************************************************************/
  72.  
  73.  
  74.  
  75. #ifdef powerc
  76. #pragma options align=mac68k
  77. #endif
  78. typedef struct cdefRsrcJMP {
  79.     long    jsrInst;
  80.     long    moveInst;
  81.     short    jmpInst;
  82.     long    jmpAddress;
  83. } cdefRsrcJMP;
  84. typedef cdefRsrcJMP *cdefRsrcJMPPtr, **cdefRsrcJMPHndl;
  85. #ifdef powerc
  86. #pragma options align=reset
  87. #endif
  88.  
  89.  
  90.  
  91. /*****************************************************************************/
  92.  
  93.  
  94.  
  95. short    gPICTCtl = rPICTCtl;
  96.  
  97. extern ControlHandle    gWhichCtlHit;
  98. extern Boolean            gWhichCtlDbl;
  99. extern Boolean            gWhichCtlTracking;
  100.  
  101. static pascal long        CPICTCtl   (short varCode, ControlHandle ctl, short msg, long parm);
  102. static pascal void        CPICTAction(ControlHandle ctl, short part);
  103. static pascal void        NoRect(GrafVerb verb, Rect *r);
  104. static pascal PicHandle    GetPICT(ControlHandle ctl, short baseID, short id);
  105.  
  106. static cdefRsrcJMPHndl    gCDEF;
  107.  
  108.  
  109.  
  110. /*****************************************************************************/
  111. /*****************************************************************************/
  112. /*****************************************************************************/
  113.  
  114.  
  115.  
  116. #pragma segment Controls
  117. static pascal long    CPICTCtl(short varCode, ControlHandle ctl, short msg, long parm)
  118. {
  119.     Rect                viewRct, r;
  120.     short                thisHilite, keepHilite, i;
  121.     unsigned long        resPICTID, id, variant, sticky, offScreen, srcOrMode;
  122.     PicHandle            pict;
  123.     ControlHandle        cc;
  124.     WindowPtr            ww, curPort, keepPort;
  125.     LayerObj            wlayer, blayer;
  126.     RgnHandle            oldClip, newClip, colorRgn;
  127.     short                txFont, txSize, txMode, fnum, depth;
  128.     Style                txFace;
  129.     QDProcs                qdp;
  130.     QDProcsPtr            oldqdp;
  131.     FontInfo            finfo;
  132.     ControlStyleInfo    cinfo;
  133.     char                hstate;
  134.     Handle                dh;
  135.     Str255                str;
  136.  
  137.     static QDRectUPP    qdrupp;
  138.  
  139.     viewRct    = (*ctl)->contrlRect;
  140.     thisHilite = (*ctl)->contrlHilite;
  141.     resPICTID  = (*ctl)->contrlRfCon & 0x0000FFFFL;
  142.     variant    = (*ctl)->contrlRfCon & 0xFFFF0000L;
  143.     sticky     = variant & 0x00010000L;
  144.     offScreen  = variant & 0x00020000L;
  145.     srcOrMode  = variant & 0x00080000L;
  146.  
  147.     switch (msg) {
  148.  
  149.         case drawCntl:
  150.  
  151.             pcpy(str, (*ctl)->contrlTitle);
  152.  
  153.             GetPort(&curPort);
  154.             if (EmptyRgn(curPort->visRgn)) offScreen = 0;
  155.                 /* We are fully clipped out, so there's no sense in going offscreen.
  156.                 ** The only reason that we don't just leave is that the application
  157.                 ** may have set up this condition with the expectation of contributing
  158.                 ** the control into a PICT. */
  159.  
  160.             if (offScreen) {
  161.                 NewLayer(&wlayer, nil, nil, curPort, 0, 0);
  162.                 if (srcOrMode) (*wlayer)->xferMode = srcOr;
  163.                 r = curPort->portRect;
  164.                 SectRect(&r, &viewRct, &r);
  165.                 (*wlayer)->dstRect = r;                /* Minimize the size of the offscreen. */
  166.                 depth = (*ctl)->contrlMin;
  167.                 if (depth < 0) {
  168.                     depth = -depth;
  169.                     depth &= 0xFF;
  170.                 }
  171.                 NewLayer(&blayer, wlayer, nil, nil, depth, 0);
  172.                 SetLayerWorld(blayer);
  173.                 InvalLayer(wlayer, r, false);
  174.             }
  175.  
  176.             if (sticky) {
  177.                 if (thisHilite < 2)
  178.                     thisHilite = (*ctl)->contrlValue;
  179.                 if (thisHilite == 2)
  180.                     thisHilite = 255;
  181.             }
  182.  
  183.             switch (thisHilite) {
  184.                 case 1:
  185.                 case 255:
  186.                     id = (thisHilite == 1) ? (resPICTID + 2) : (resPICTID + 4);
  187.  
  188.                     SetResLoad(false);
  189.                     if (!GetPICT(ctl, resPICTID, id)) id = resPICTID;
  190.                     SetResLoad(true);
  191.  
  192.                     (*ctl)->contrlRfCon = (id + variant - offScreen);    /* Prevent nesting of offscreen. */
  193.                     keepHilite = (*ctl)->contrlHilite;
  194.                     (*ctl)->contrlHilite = 99;
  195.                     CPICTCtl(varCode, ctl, msg, parm);
  196.                     str[0] = 0;                                            /* Just draw the text once. */
  197.                     (*ctl)->contrlHilite = keepHilite;
  198.                     (*ctl)->contrlRfCon  = (resPICTID | variant);
  199.                     if (thisHilite == 1)
  200.                         if (id == resPICTID)
  201.                             InvertRect(&viewRct);
  202.                                 /* If there is no hilite==1 'PICT', invert the base 'PICT'. */
  203.                     break;
  204.                 default:
  205.                     if (!(variant & 0x01)) resPICTID += (*ctl)->contrlValue;
  206.  
  207.                     EraseRect(&viewRct);        /* Start pict fresh and clean. */
  208.  
  209.                     pict = GetPICT(ctl, resPICTID, resPICTID);
  210.                     if (!pict) {
  211.                         FrameRect(&viewRct);
  212.                         break;
  213.                     }
  214.  
  215.                     hstate = HGetState((Handle)pict);        /* Lock it before moving something */
  216.                     HLock((Handle)pict);                    /* causes it to purge.               */
  217.  
  218.                     GetPort(&keepPort);
  219.                     SetPort((*ctl)->contrlOwner);
  220.                     depth = 4;
  221.                     if ((*ctl)->contrlMin < 0) {
  222.                         depth = -(*ctl)->contrlMin;
  223.                         if (depth & 0xFF00)
  224.                             depth >>= 8;
  225.                         else
  226.                             depth  &= 0xFF;
  227.                     }
  228.                     colorRgn = LocalScreenDepthRegion(depth);
  229.                     SetPort(keepPort);
  230.  
  231.                     oldClip = NewRgn();
  232.                     newClip = NewRgn();
  233.                     GetClip(oldClip);            /* Draw color area first. */
  234.                     RectRgn(newClip, &curPort->portRect);
  235.                     SectRgn(newClip, colorRgn, newClip);
  236.                     SetClip(newClip);
  237.                     DrawPicture(pict, &viewRct);
  238.                     HSetState((Handle)pict, hstate);
  239.  
  240.                     pict = GetPICT(ctl, resPICTID, resPICTID + 1);
  241.                     if (!pict)
  242.                         pict = GetPICT(ctl, resPICTID, resPICTID);
  243.                     if (pict) {
  244.                         hstate = HGetState((Handle)pict);
  245.                         HLock((Handle)pict);
  246.                         RectRgn(newClip, &curPort->portRect);    /* Draw b/w pict area. */
  247.                         DiffRgn(newClip, colorRgn, newClip);
  248.                         SetClip(newClip);
  249.                         DrawPicture(pict, &viewRct);
  250.                         HSetState((Handle)pict, hstate);
  251.                     }
  252.  
  253.                     SetClip(oldClip);
  254.                     DisposeRgn(oldClip);
  255.                     DisposeRgn(newClip);
  256.                     DisposeRgn(colorRgn);
  257.  
  258.                     break;
  259.             }
  260.  
  261.             if (str[0]) {
  262.                 GetPort(&ww);
  263.                 txFont = ww->txFont;
  264.                 txFace = ww->txFace;
  265.                 txSize = ww->txSize;
  266.                 if (!((variant >> 16) & useWFont)) {
  267.                     TextFont(systemFont);
  268.                     TextFace(normal);
  269.                     TextSize(0);
  270.                 }
  271.                 else {
  272.                     if (GetControlStyle(ctl, &cinfo)) {
  273.                         TextFace(cinfo.fontStyle);
  274.                         fnum = systemFont;
  275.                         if (cinfo.font[0])
  276.                             GetFNum(cinfo.font, &fnum);
  277.                         TextFont(fnum);
  278.                         TextSize(cinfo.fontSize);
  279.                     }
  280.                 }
  281.  
  282.                 oldqdp = ww->grafProcs;
  283.                 if (oldqdp)
  284.                     BlockMove(oldqdp, &qdp, sizeof(QDProcs));
  285.                 else
  286.                     SetStdProcs(&qdp);
  287.                 if (!qdrupp) {
  288. #if USES68KINLINES
  289.                     qdrupp = (QDRectUPP)NoRect;
  290. #else
  291.                     qdrupp = NewQDRectProc(NoRect);
  292. #endif
  293.                 }
  294.                 qdp.rectProc = qdrupp;
  295.                 ww->grafProcs = &qdp;
  296.                 txMode = ww->txMode;
  297.                 TextMode(srcOr);
  298.  
  299.                 GetFontInfo(&finfo);
  300.                 viewRct.top += (finfo.ascent + finfo.descent) / 2;
  301.                 if (viewRct.top < viewRct.bottom)
  302.                     TETextBox(str + 1, str[0], &viewRct, teCenter);
  303.  
  304.                 ww->grafProcs = oldqdp;
  305.                 TextMode(txMode);
  306.  
  307.                 TextFont(txFont);
  308.                 TextFace(txFace);
  309.                 TextSize(txSize);
  310.             }
  311.  
  312.             if (offScreen) {
  313.                 UpdateLayer(wlayer);
  314.                 ResetLayerWorld(blayer);
  315.                 DisposeThisAndBelowLayers(wlayer);
  316.             }
  317.  
  318.             break;
  319.  
  320.         case testCntl:
  321.  
  322.             if ((*ctl)->contrlHilite == 255) return(0);
  323.                 /* Control disabled, so no click.  (We probably don't get called in this case. */
  324.  
  325.             if (!sticky) return(PtInRect(*(Point *)&parm, &viewRct));
  326.                 /* Don't make user call WhichControl unless the variant
  327.                 ** is for double-clicking.  (Then it has to be called.) */
  328.  
  329.             if (ctl != gWhichCtlHit) return(0);
  330.                 /* WhichControl already found the control hit.  Unless it is the one
  331.                 ** found by WhichControl, consider it unhit. */
  332.  
  333.             if (gWhichCtlTracking) return(1);
  334.                 /* We already handled it, but the control manager is insistent. */
  335.  
  336.             if (!(*ctl)->contrlValue) {            /* Turn off any other controls in this family. */
  337.                 ww = (*ctl)->contrlOwner;
  338.                 for (cc = nil; (cc = CPICTNext(ww, cc, 1, true)) != nil;) {
  339.                     if (cc != ctl) {
  340.                         if (((*cc)->contrlMax & 0xFFF0) == ((*ctl)->contrlMax & 0xFFF0)) {
  341.                             if ((*cc)->contrlValue) {
  342.                                 (*cc)->contrlValue  = 0;
  343.                                 (*cc)->contrlHilite = 0;
  344.                                 CPICTCtl(varCode, cc, drawCntl, 0);
  345.                             }
  346.                         }
  347.                     }
  348.                 }
  349.             }
  350.  
  351.             (*ctl)->contrlValue = 1;
  352.             if (gWhichCtlDbl)                        /* If user double-clicked... */
  353.                 if (!((*ctl)->contrlMax & 0x01))    /* If double-clicking allowed... */
  354.                     (*ctl)->contrlValue = 2;
  355.  
  356.             CPICTCtl(varCode, ctl, drawCntl, 0);
  357.  
  358.             gWhichCtlTracking = true;
  359.             return(1);
  360.  
  361.             break;
  362.  
  363.         case calcCRgns:
  364.         case calcCntlRgn:
  365.             if (msg == calcCRgns)
  366.                 parm &= 0x00FFFFFF;
  367.             RectRgn((RgnHandle)parm, &viewRct);
  368.             break;
  369.  
  370.         case initCntl:
  371.             (*ctl)->contrlData = nil;
  372.             break;
  373.  
  374.         case dispCntl:
  375.             dh = (*ctl)->contrlData;
  376.             if (dh) {
  377.                 for (i = 0; i < 6; ++i) {
  378.                     pict = (*(PicHandle **)dh)[i];
  379.                     if (pict) KillPicture(pict);
  380.                 }
  381.                 DisposeHandle(dh);
  382.                 (*ctl)->contrlData = nil;
  383.             }
  384.             break;
  385.  
  386.         case posCntl:
  387.             break;
  388.  
  389.         case thumbCntl:
  390.             break;
  391.  
  392.         case dragCntl:
  393.             break;
  394.  
  395.         case autoTrack:
  396.             break;
  397.     }
  398.  
  399.     return(0);
  400. }
  401.  
  402.  
  403.  
  404. /*****************************************************************************/
  405.  
  406.  
  407.  
  408. #pragma segment Controls
  409. ControlHandle    CPICTNew(WindowPtr window, Rect *r, StringPtr title, Boolean vis, short val,
  410.                          short min, short max, short viewID, short refcon)
  411. {
  412.     WindowPtr        oldPort;
  413.     Rect            viewRct, rct;
  414.     Boolean            err;
  415.     ControlHandle    viewCtl;
  416.     unsigned long    variant;
  417.     PicHandle        pict;
  418.  
  419.     static ControlActionUPP    cupp;
  420.     static ControlDefUPP    cdefupp;
  421.  
  422.     GetPort(&oldPort);
  423.     SetPort(window);
  424.  
  425.     viewRct = *r;
  426.     viewCtl = nil;
  427.  
  428.     err = false;
  429.  
  430.     if (!gCDEF) {
  431.         gCDEF = (cdefRsrcJMPHndl)GetResource('CDEF', (viewID / 16));
  432.         if (gCDEF) {
  433.             if (!cdefupp) {
  434.                 cdefupp = NewControlDefProc(CPICTCtl);
  435.             }
  436.             (*gCDEF)->jmpAddress = (long)cdefupp;
  437.             if (TrapExists(_HWPriv))
  438.                 FlushInstructionCache();
  439.                     /* Make sure that instruction caches don't kill us. */
  440.         }
  441.         else err = true;
  442.     }
  443.  
  444.     if (!err) {
  445.         if (viewID & 0x04) {
  446.             viewID -= 0x04;
  447.             pict = (PicHandle)GetResource('PICT', refcon);
  448.             if (pict) {
  449.                 rct = (*pict)->picFrame;
  450.                 viewRct.right  = viewRct.left + (rct.right  - rct.left);
  451.                 viewRct.bottom = viewRct.top  + (rct.bottom - rct.top);
  452.             }
  453.         }
  454.         variant   = (viewID & 0x0F);
  455.         variant <<= 16;
  456.         viewCtl = NewControl(window, &viewRct, title, vis, val, min, max, viewID, (variant | refcon));
  457.         if (viewCtl) {
  458.             if (!cupp) cupp = NewControlActionProc(CPICTAction);
  459.             SetControlAction(viewCtl, cupp);
  460.         }
  461.         else
  462.             err = true;
  463.     }
  464.  
  465.     SetPort(oldPort);
  466.  
  467.     return(viewCtl);
  468. }
  469.  
  470.  
  471.  
  472. /*****************************************************************************/
  473.  
  474.  
  475.  
  476. #pragma segment Controls
  477. ControlHandle    CPICTNext(WindowPtr window, ControlHandle ctl, short dir, Boolean justActive)
  478. {
  479.     ControlHandle    nextCtl, priorCtl;
  480.  
  481.     if (!window) return(nil);
  482.     if (!gCDEF)  return(nil);
  483.  
  484.     if (dir > 0) {
  485.         if (!ctl)
  486.             ctl = ((WindowPeek)window)->controlList;
  487.         else
  488.             ctl = (*ctl)->nextControl;
  489.         while (ctl) {
  490.             if ((!justActive) || ((*ctl)->contrlVis)) {
  491.                 if ((!justActive) || ((*ctl)->contrlHilite != 255)) {
  492.                     if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gCDEF))
  493.                         return(ctl);
  494.                             /* The handle may be locked, which means that the hi-bit
  495.                             ** may be on, thus invalidating the compare.  Dereference the
  496.                             ** handles to get rid of this possibility. */
  497.                 }
  498.             }
  499.             ctl = (*ctl)->nextControl;
  500.         }
  501.         return(ctl);
  502.     }
  503.  
  504.     nextCtl = ((WindowPeek)window)->controlList;
  505.     for (priorCtl = nil; ;nextCtl = (*nextCtl)->nextControl) {
  506.         if ((!nextCtl) || (nextCtl == ctl)) return(priorCtl);
  507.         if ((!justActive) || ((*nextCtl)->contrlVis)) {
  508.             if ((!justActive) || ((*nextCtl)->contrlHilite != 255)) {
  509.                 if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gCDEF))
  510.                     priorCtl = nextCtl;
  511.                         /* The handle may be locked, which means that the hi-bit
  512.                         ** may be on, thus invalidating the compare.  Dereference the
  513.                         ** handles to get rid of this possibility. */
  514.             }
  515.         }
  516.     }
  517. }
  518.  
  519.  
  520.  
  521. /*****************************************************************************/
  522.  
  523.  
  524.  
  525. #pragma segment Controls
  526. Boolean    IsPICTCtl(ControlHandle ctl)
  527. {
  528.     if (ctl)
  529.         if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gCDEF))
  530.             return(true);
  531.                 /* The handle may be locked, which means that the hi-bit
  532.                 ** may be on, thus invalidating the compare.  Dereference the
  533.                 ** handles to get rid of this possibility. */
  534.     return(false);
  535. }
  536.  
  537.  
  538.  
  539. /*****************************************************************************/
  540.  
  541.  
  542.  
  543. #pragma segment Controls
  544. static pascal void    CPICTAction(ControlHandle ctl, short part)
  545. {
  546.     static short    lastPart = 0;
  547.  
  548.     if (lastPart != part) {
  549.         lastPart = part;
  550.         CPICTCtl(0, ctl, drawCntl, part);
  551.     }
  552. }
  553.  
  554.  
  555.  
  556. /*****************************************************************************/
  557.  
  558.  
  559.  
  560. #pragma segment Controls
  561. static pascal void    NoRect(GrafVerb verb, Rect *r)
  562. {
  563. #ifndef __MWERKS__
  564. #pragma unused (verb, r)
  565. #endif
  566. }
  567.  
  568.  
  569.  
  570. /*****************************************************************************/
  571.  
  572.  
  573.  
  574. #pragma segment Controls
  575. static pascal PicHandle    GetPICT(ControlHandle ctl, short baseID, short id)
  576. {
  577.     Handle        dh;
  578.     PicHandle    pict;
  579.  
  580.     dh = (*ctl)->contrlData;
  581.     if (dh)
  582.         pict = (*(PicHandle **)dh)[id - baseID];
  583.     else
  584.         pict = (PicHandle)GetResource('PICT', id);
  585.  
  586.     return(pict);
  587. }
  588.  
  589.  
  590.  
  591.